package com.third.bank.filter;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.third.bank.exception.BusinessException;
import com.third.bank.service.UserService;
import com.third.bank.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * 每次亲求进入控制器之前，判断是否存在token
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {

    //    token存活时间
//    private static final long MAX_INACTIVE_TIME = 1000 * 60;
    private static final long MAX_INACTIVE_TIME = 1000 * 30 * 100;

    @Autowired
    private UserService userService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("Authorization");

        // 如果请求是注册或登录请求，则不需要验证 token
        if (request.getRequestURI().contains("/register") || request.getRequestURI().contains("/login") || request.getRequestURI().contains("/sms")) {
            return true;
        } else {
            System.out.println(token);
            System.out.println(stringRedisTemplate.opsForValue().get(token));
//        确认redis中是否有这个token
            boolean flag = Boolean.TRUE.equals(stringRedisTemplate.hasKey(token));

            if (StringUtils.isNotBlank(token) && JwtUtil.checkToken(token) && flag) {
                // 解析Token中保存的最后访问时间
                long lastAccessedTime = Long.parseLong(stringRedisTemplate.opsForValue().get(token));
                long currentTime = System.currentTimeMillis();
                if (Math.abs(currentTime - lastAccessedTime) > MAX_INACTIVE_TIME) {
                    // 如果超时，删除redis中保存的Token并重定向到登录页面
                    stringRedisTemplate.delete(token);
//                将用户状态改为未登录
                    userService.logout(token);
                    throw new BusinessException(302, "toke已过期");
//                    response.sendRedirect("/login");
//                    return false;
                } else {
                    // 更新Token中保存的最后访问时间
                    String s = String.valueOf(new Date().getTime());
                    System.out.println(s);
                    stringRedisTemplate.opsForValue().set(token, s);
                }
            } else {
//            转向登录
                throw new BusinessException(302, "toke已过期");
//                response.sendRedirect("/login");
//                return false;
            }

            return true;
        }


    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    /**
     * 获取该token的最后访问时间
     *
     * @param token
     * @return
     */
    private long getExpirationTimeFromToken(String token) {
        // 解析Token并获取过期时间，具体实现可以根据自己的需要进行修改
        return JwtUtil.getExpirationTime(token).getTime();
    }

    /**
     * 删除响应头中的token
     *
     * @param response
     */
    private void deleteTokenFromResponse(HttpServletResponse response) {
        // 从响应头中删除Token，具体实现可以根据自己的需要进行修改
        response.setHeader("Authorization", "");
    }

    /**
     * 跟新最新访问时间
     *
     * @param response
     * @param lastAccessedTime
     */
    private void updateTokenExpirationTime(HttpServletResponse response, String token, long lastAccessedTime) {
        // 更新Token中保存的最后访问时间，具体实现可以根据自己的需要进行修改
        String newToken = JwtUtil.refreshExpirationTime(token, new Date(lastAccessedTime));

        System.out.println(newToken);
        Date expirationTime = JwtUtil.getExpirationTime(newToken);
        System.out.println("=====================");
        System.out.println(expirationTime);
        System.out.println("=====================");

        response.setHeader("Authorization", newToken);
    }
}
